package server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Creates a concurrent TCP server to accept multiple simultaneous queries.
 * 
 * @author the_james_marq
 * @version 26 October 13
 */
public class ConcurrentTCPSpellingServer {

	private static int DEFAULT_THREAD_COUNT = 10;
	
	/**
	 * Main method for ConcurrentTCPSpellingServer
	 * 
	 * @param args Command line arguments.
	 */
	public static void main(String[] args) {

		ThreadFactory threadFactory = Executors.defaultThreadFactory();
		RejectedExecutionHandlerImpl rejectionHandler = new RejectedExecutionHandlerImpl();
		
		try{
			Integer.parseInt(args[0]);
		} catch(NumberFormatException e) {
			Log.err("Port number must be numeric.");
			System.exit(0);
		}
		
		ThreadPoolExecutor thread_pool = null;
		
		if(args.length == 3) {
			thread_pool = new ThreadPoolExecutor(2, Integer.parseInt(args[2]),
				5, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), threadFactory, 
				rejectionHandler);
			
		} else if(args.length == 2) {
			thread_pool = new ThreadPoolExecutor(2, DEFAULT_THREAD_COUNT,
					5, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), threadFactory, 
					rejectionHandler);
		} else {
			Log.err("Usage: java ConcurrentTCPSpellingServer <port> <word-list>");
			System.exit(0);
		}
		
		Log.out("Configuring for " + thread_pool.getMaximumPoolSize() + " simultaneous " +
				"sessions.");	
	    
		ServerSocket server;
	    
	    try{

	        server= new ServerSocket(Integer.parseInt(args[0]));
	        Log.out("Server socket opened on port " + server.getLocalPort());

	        while(true) {
	            try{
	                Socket client = server.accept();
	                WordList word_list = new WordList(args[1]);
	                
	                //Create new runnable for request and execute it.
	                Runnable tcpserv = new TCPSpellingServerThread(client, word_list);
	                thread_pool.execute(tcpserv);

	            }
	            catch (IOException e) {
	                Log.err("Unable to listen on port.");
	            }
	        }

	    }catch (IOException el){
	        Log.err("Unable to create server.");
	    }

		
	}

}
